package com.pan.admin.quartz.http;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.log.LogLevel;
import com.gitee.apanlh.util.net.http.HttpClientBuilder;
import com.gitee.apanlh.util.net.http.HttpResponse;
import com.gitee.apanlh.web.http.HttpMethod;
import com.pan.admin.quartz.entity.LowBalanceNoticeVO;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 李源聪
 */
@Component
public class FeiShuHttpSend {

    /**
     * 飞书机器人通知
     *
     * @param lowBalanceNoticeList 用户信息
     */
    public void feiShuChatBotNotice(List<LowBalanceNoticeVO> lowBalanceNoticeList) {

        // 获取所有手机号
        List<String> mobileList = lowBalanceNoticeList.stream().map(LowBalanceNoticeVO::getPhoneNumber).collect(Collectors.toList());

        String token = this.tenantAccessToken();
        Map<String, String> userIdMap = this.batchGetUserId(mobileList, token);

        List<Map<Object, Object>> list = lowBalanceNoticeList.stream().map(lowBalanceNoticeVO -> {
            Map<Object, Object> rowMap = new LinkedHashMap<>();
            rowMap.put("customer_name", lowBalanceNoticeVO.getName());
            rowMap.put("customer_scale", lowBalanceNoticeVO.getBalance());
            rowMap.put("customer_poc", userIdMap.get(lowBalanceNoticeVO.getPhoneNumber()));
            return rowMap;
        }).collect(Collectors.toList());

        String uid = "19079768-e447-40f9-84d1-18e478c6b7d9";
        String msgType = "interactive";
        String secret = "7jLVdUBC4fwemgXnpsKywb";

        int currentTimeMillis = (int) (System.currentTimeMillis() / 1000);
        String sign;
        try {
            sign = GenSign(secret,  currentTimeMillis);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("加密时错误：" + e.getMessage(), e);
        }

        Map<Object, Object> bodyMap = new LinkedHashMap<>();
        bodyMap.put("msg_type", msgType);
        bodyMap.put("timestamp", currentTimeMillis);
        bodyMap.put("sign", sign);
        bodyMap.put("card", MapUtils.newHashMap(newMap -> {
            newMap.put("type", "template");
            newMap.put("data", MapUtils.newHashMap(dataMap -> {
                dataMap.put("template_id", "AAq4TOstgvMmn");
                dataMap.put("template_version_name", "1.0.7");
                dataMap.put("template_variable", MapUtils.newHashMap(templateVariableMap -> {
                    templateVariableMap.put("table_raw_array_1", list);
                    templateVariableMap.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                }));
            }));
        }));

        String reqJson = JSONObject.toJSONString(bodyMap);

        String url = "https://open.feishu.cn/open-apis/bot/v2/hook/" + uid;

        HttpResponse build = HttpClientBuilder.builder(url, HttpMethod.POST)
                .withBodyJson(reqJson)
                .withHeader((headerMap) -> headerMap.put("Content-Type", "application/json"))
                .withLogLevel(LogLevel.WARN)
                .withErrorLogLevel(LogLevel.WARN)
                .build();
        String respStr = build.getStr();
        JSONObject jsonObject = JsonUtils.get(respStr);
        Integer code = jsonObject.getInteger("code");
        if (!Eq.object(code, 0)) {
            throw new RuntimeException("发送失败:" + respStr);
        }
    }

    /**
     * 生成加密信息
     *
     * @param secret    飞书机器人的密钥
     * @param timestamp 当前时间戳
     * @return 加密后的信息
     */
    private static String GenSign(String secret, int timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
        // 把timestamp+"\n"+密钥当做签名字符串
        String stringToSign = timestamp + "\n" + secret;
        // 使用HmacSHA256算法计算签名
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(new byte[] {});
        return new String(Base64.encodeBase64(signData));
    }

    /**
     * 获取token
     * PS：目前请求量不大，直接调用该方法获取token即可，不需要缓存token，暂时没用用上expire
     *
     * @return 返回token
     */
    private String tenantAccessToken() {
        // 飞书应用的appId
        String appId = "cli_a8ac439cf53bd00c";
        // 飞书应用的appSecret
        String appSecret = "lmcT0M4vJ1KZBZ0C7zPpBhcohtuUisSX";
        String url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";

        Map<Object, Object> bodyMap = new LinkedHashMap<>();
        bodyMap.put("app_id", appId);
        bodyMap.put("app_secret", appSecret);
        String reqJson = JSONObject.toJSONString(bodyMap);
        HttpResponse build = HttpClientBuilder.builder(url, HttpMethod.POST)
                .withBodyJson(reqJson)
                .withHeader(headerMap -> headerMap.put("Content-Type", "application/json; charset=utf-8"))
                .withLogLevel(LogLevel.WARN)
                .withErrorLogLevel(LogLevel.WARN)
                .build();
        JSONObject jsonObject = JsonUtils.get(build.getStr());
        Integer code = jsonObject.getInteger("code");
        if (code == 0){
            return jsonObject.getString("tenant_access_token");
        }
        return null;
    }

    /**
     * 通过手机号获取飞书用户id
     *
     * @param mobileList 手机号数组
     * @param tenantAccessToken token
     *
     * @return 用户手机号和飞书用户id的map
     *
     */
    private Map<String, String> batchGetUserId(List<String> mobileList, String tenantAccessToken){
        String url1 = "https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id";
        Map<Object, Object> bodyMap = new LinkedHashMap<>();
        bodyMap.put("mobiles", mobileList);
        bodyMap.put("include_resigned", true);
        String reqJson1 = JSONObject.toJSONString(bodyMap);
        HttpResponse build = HttpClientBuilder.builder(url1, HttpMethod.POST)
                .withBodyJson(reqJson1)
                .withHeader(headerMap -> {
                    headerMap.put("Content-Type", "application/json; charset=utf-8");
                    headerMap.put("Authorization", "Bearer "+tenantAccessToken); // 新增的请求头
                })
                .withLogLevel(LogLevel.WARN)
                .withErrorLogLevel(LogLevel.WARN)
                .build();

        Map<String, String> result = new HashMap<>();
        JSONObject jsonObject = JsonUtils.get(build.getStr());
        Integer code = jsonObject.getInteger("code");
        if (code == 0){
            JSONObject data = jsonObject.getJSONObject("data");
            JSONArray userList = data.getJSONArray("user_list");
            for (int i = 0; i < userList.size(); i++) {
                JSONObject user = userList.getJSONObject(i);
                result.put(user.getString("mobile"), user.getString("user_id"));
            }
        }
        return result;
    }

}
